package com.ldn.controller.api;

import cn.dev33.satoken.annotation.SaCheckLogin;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.util.ClassUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.ldn.basic.dispose.exception.AppException;
import com.ldn.basic.enums.OssTypeEnums;
import com.ldn.basic.utils.DataUtil;
import com.ldn.basic.utils.ali.ALiOssUtil;
import com.ldn.basic.utils.qiniu.QNOssUtil;
import com.ldn.controller.dto.UploadDto;
import com.ldn.controller.vo.UploadVo;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author 李大牛家的牛 (scafel@163.com)
 * @createDate 2024/7/15 - 10:55
 * @description ...
 **/
@Tag(name = "文件上传", description = "文件上传相关接口")
@RestController
@RequestMapping("/api/upload")
@Slf4j
public class UploadController {


    @Operation(summary = "文件上传到服务器本地", description = "文件上传到服务器本地")
    @SaCheckLogin
    @PostMapping("/local")
    public UploadVo uploadLocal(@Validated UploadDto dto) {
        // 获取上传配置
        boolean isOss = false;
        if (isOss){
            return uploadOss(dto);
        }else {
            return uploadDisk(dto);
        }
    }

    public File uploadFile(UploadDto dto) throws IOException {
        MultipartFile file = dto.getFile();
        String fileName = file.getOriginalFilename();
        if (fileName == null ||fileName.isBlank()){
            throw new AppException("文件名不能为空");
        }
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        String name = DataUtil.getCode(dto.getPrefix());
        String path = Objects.requireNonNull(Objects.requireNonNull(ClassUtils.getDefaultClassLoader()).getResource("")).getPath();
        File classDir = new File(path);
        String folderName = dto.getGroup() + "/" + dto.getPrefix();
        File dir = new File(classDir.getParent() + "/static/"  + folderName);
        if (!dir.exists()){
            if (!dir.mkdirs()){
                throw new AppException("目录创建失败");
            }
        }
        File localFile = File.createTempFile(name, suffix, dir);
        file.transferTo(localFile);
        if (!localFile.exists()){
            log.error("文件保存失败 ex =>{}", localFile);
        }
        Files.move(localFile.toPath(), localFile.toPath().resolveSibling(name + suffix));
        File fileThumbnail = new File(dir  + "/" + name + suffix );
        // 是否生成缩略图
        boolean isThumbnail = false;
        if (!isThumbnail){
            return fileThumbnail;
        }
        if (isImage(suffix) ) {
            File thumbnailsTempFile = File.createTempFile("thumbnails-" + name, suffix, dir);
            Thumbnails.of(fileThumbnail).scale(0.5f).outputQuality(0.5f).toFile(thumbnailsTempFile);
            Files.move(thumbnailsTempFile.toPath(), thumbnailsTempFile.toPath().resolveSibling("thumbnails-" + name + suffix));
            return new File(dir  + "/thumbnails-" + name + suffix );
        }
        return fileThumbnail;
    }

    public static boolean isImage(String extension) {
        String[] imageExtension = new String[]{".jpeg", ".jpg", ".gif", ".bmp", ".png"};
        for (String e : imageExtension) {
            if (extension.toLowerCase().equals(e)) {
                return true;
            }
        }
        return false;
    }

    public UploadVo uploadDisk(UploadDto dto) {
        // 获取设置中的云存储访问路径
        String yccurl = "";
        try {
            String folderName = dto.getGroup() + "/" + dto.getPrefix();
            File localFile = uploadFile(dto);
            UploadVo vo = new UploadVo();
            vo.setFileName(localFile.getName());
            vo.setFilePath(folderName);
            vo.setFileUrl(yccurl + "/" +vo.getFilePath()+"/"+vo.getFileName());
            return vo;
        } catch (Exception e) {
            log.error("文件保存失败 ", e);
            throw new AppException("文件保存失败");
        }
    }

    public UploadVo uploadOss(UploadDto dto) {
        // 获取设置中的云存储存储方案类型
        OssTypeEnums typeEnum = OssTypeEnums.getType("qiniu");
        return switch (typeEnum) {
            case QINIU -> uploadToQiniu(dto);
            case ALIYUN -> uploadToAliyun(dto);
            case TENCENT -> uploadToTencent(dto);
            default -> throw new AppException("未配置云存储类型");
        };
    }

    public UploadVo uploadToQiniu(UploadDto dto) {
        try {
            String folderName = dto.getGroup() + "/" + dto.getPrefix();
            File localFile = uploadFile(dto);
            Map<String, String> settingVo = new HashMap<>();
            // 获取七牛云存储配置并转换为Map
            QNOssUtil.uploadToOss(
                    settingVo.get("qiniuossid"),
                    settingVo.get("qiniuosskey"),
                    settingVo.get("qiniuossbucket"),
                    settingVo.get("qiniuosspoint"),
                    folderName,
                    localFile
            );
            UploadVo vo = new UploadVo();
            vo.setFileName(localFile.getName());
            vo.setFilePath(folderName);
            // vo.setFileUrl(yccurl.getWss003() + "/" +vo.getFilePath()+"/"+vo.getFileName());
            return vo;
        }catch (Exception e){
            log.error("文件上传失败 ", e);
            throw new AppException("文件上传失败");
        }
    }

    public UploadVo uploadToAliyun(UploadDto dto) {
        try {
            String folderName = dto.getGroup() + "/" + dto.getPrefix();
            File localFile = uploadFile(dto);
            Map<String, String> settingVo = new HashMap<>();
            // 获取阿里云存储配置并转换为Map
            ALiOssUtil.uploadToOss(
                    settingVo.get("aliossid"),
                    settingVo.get("aliosskey"),
                    settingVo.get("aliossbucket"),
                    settingVo.get("aliosspoint"),
                    folderName,
                    localFile
            );
            UploadVo vo = new UploadVo();
            vo.setFileName(localFile.getName());
            vo.setFilePath(folderName);
            // vo.setFileUrl(yccurl.getWss003() + "/" +vo.getFilePath()+"/"+vo.getFileName());
            return vo;
        }catch (Exception e){
            log.error("文件上传失败 ", e);
            throw new AppException("文件上传失败");
        }
    }

    public UploadVo uploadToTencent(UploadDto dto) {
        return null;
    }
}
